package main

import (
	"fmt"
	"os"
	"runtime/trace"
	"sync"
	"time"
)

// 扇入 Fan-In，FIFO队列，主要是多个管道写入到一个管道，一个管道写出
func main() {
	// =============================================
	// 扇出 Fanout 多个管道写出，一个管道写入
	trace.Start(os.Stderr)
	var wg sync.WaitGroup
	wg.Add(5)
	pool(&wg, 5)
	wg.Wait()
	trace.Stop()
	// =============================================
	// var c1 = boring(1)
	// var c2 = boring(2)
	// for i := 0; i < 10; i++ {
	// 	select {
	// 	case v := <-c1:
	// 		fmt.Println(v)
	// 	case v := <-c2:
	// 		fmt.Println(v)
	// 	default:
	// 		time.Sleep(1 * time.Millisecond)
	// 	}
	// 	time.Sleep(1 * time.Second)
	// }

	// result := fanIn(boring(1), boring(2))

	// for i := 0; i < 10; i++ {
	// 	fmt.Println(<-result)
	// }
	// =============================================

}

// 扇入，FIFO队列，主要是多个管道写入到一个管道，一个管道写出
func boring(msg int) <-chan int {
	c := make(chan int)
	go func() {
		i := 1
		for {
			c <- msg*1000 + i
			i++
		}
	}()
	return c
}

// 扇入，FIFO队列，主要是多个管道写入到一个管道，一个管道写出

func fanIn(input1, input2 <-chan int) chan int {
	var c = make(chan int)
	go func() {
		for {
			c <- <-input1
		}
	}()
	go func() {
		for {
			c <- <-input2
		}
	}()
	return c
}

// =============================================
func workers(wg *sync.WaitGroup, c <-chan int) {
	// 启动多个管道写出<多线程执行>
	defer wg.Done()
	for {

		task, ok := <-c
		if !ok {
			return
		}
		fmt.Println(task)
		time.Sleep(100 * time.Millisecond)
	}
}
func pool(wg *sync.WaitGroup, w int) {
	// 启动一个管道写入
	var c = make(chan int)
	for i := 0; i < w; i++ {
		time.Sleep(10 * time.Millisecond)

		go workers(wg, c)
	}
	for i := 0; i < w*10; i++ {
		time.Sleep(1 * time.Millisecond)

		c <- i
	}
	close(c)
}
